package com.ykl.demo.entity;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.ykl.base.restful.validator.OptionVals;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.validator.constraints.Length;
import org.springframework.util.CollectionUtils;

import javax.persistence.*;
import javax.validation.Constraint;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import javax.validation.Payload;
import javax.validation.constraints.Digits;
import javax.validation.constraints.NotNull;
import java.lang.annotation.*;
import java.math.BigDecimal;
import java.util.*;

/**
 * 主表：SPC_ROOM  从表：无  关联：无.
 */
@Data
@Entity
@Table(name = "SPC_ROOM")
@SpcRoom.SpcRoomTypeId(message = "机房类型(typeId),与机房等级不符.")
public class SpcRoom {

    @Target( { ElementType.TYPE, ElementType.ANNOTATION_TYPE })
    @Retention(RetentionPolicy.RUNTIME)
    @Constraint(validatedBy = SpcRoom.SpcRoomTypeIdValidator.class)
    @Documented
    public @interface SpcRoomTypeId {
        String message() default "";

        Class<?>[] groups() default {};

        Class<? extends Payload>[] payload() default {};

    }

    @Slf4j
    public static class SpcRoomTypeIdValidator  implements ConstraintValidator<SpcRoomTypeId, SpcRoom> {

        private final static Map<String, List<String>> SPC_ROOM_TYPE_DICT;

        static{
            SPC_ROOM_TYPE_DICT = new HashMap<>();
            SPC_ROOM_TYPE_DICT.put("90218",Arrays.asList("2050060","2050061","2050062","2050063","2050064","2050172",
                    "2050065","2050066","2050067","2050068","2050069","2050070","2050053"));
            SPC_ROOM_TYPE_DICT.put("90219",Arrays.asList("2050071","2050072","2050073","2050074","2050075"));
            SPC_ROOM_TYPE_DICT.put("90230",Arrays.asList("2050120"));
            SPC_ROOM_TYPE_DICT.put("90220",Arrays.asList("2050076"));
            SPC_ROOM_TYPE_DICT.put("90221",Arrays.asList("2050150","2050151","2050121"));
        }

        public void initialize(SpcRoomTypeId ann) {

        }

        public boolean isValid(SpcRoom val, ConstraintValidatorContext ctx) {

            if(val.classId==null||val.typeId==null){
                return false;
            }

            String strClassId=Integer.toString(val.classId);
            String strTypeId=Integer.toString(val.typeId);

            List<String> ls = SPC_ROOM_TYPE_DICT.get(strClassId);
            if(!CollectionUtils.isEmpty(ls)){
                return ls.contains(strTypeId);
            }

            return false;
        }
    }


    /**
     * SPC_ROOM	ROOM_ID	机房ID	机房关键字ID, 该ID全网唯一。	CHAR(24)	M
     */
    @Id
    @org.springframework.data.annotation.Id
    @GeneratedValue(generator = "snowflakeIdentifierGenerator",
            strategy = GenerationType.IDENTITY)
    @GenericGenerator(
            name = "snowflakeIdentifierGenerator",
            strategy = "com.ykl.base.jpa.SnowflakeIdentifierGenerator"
    )
    @Column(
            name = "ROOM_ID",
            columnDefinition = "VARCHAR(24) COMMENT '机房ID\t机房关键字ID, 该ID全网唯一。'",
            nullable = false
    )
    @ApiModelProperty(value = "机房ID",notes = "机房关键字ID, 该ID全网唯一。")
    @Length(max = 24, message = "机房id最多24字符")
    private String roomId;

    /**
     * SPC_ROOM	CHINA_NAME	机房名称	具体资源在资源管理系统中的唯一名称。 	VARCHAR2(240)	M
     */
    @Column(
            name = "CHINA_NAME",
            columnDefinition = "VARCHAR(240) COMMENT '机房名称,具体资源在资源管理系统中的唯一名称。'",
            nullable = false
    )
    @ApiModelProperty(value = "机房名称", notes = "具体资源在资源管理系统中的唯一名称。")
    @Length(max = 240, message = "机房名称最多240字符")
    @NotNull(message = "机房名称不能为空")
    private String chinaName;

    /**
     * SPC_ROOM	STATION_ID	所属局站	机房所在局站的ID，引用局站表SPC_STATION.STATION_ID字段 	CHAR(24)	M
     */
    @Column(
            name = "STATION_ID",
            columnDefinition = "VARCHAR(240) COMMENT '所属局站\t机房所在局站的ID，引用局站表SPC_STATION.STATION_ID字段。'",
            nullable = false
    )
    @ApiModelProperty(value = "所属局站", notes = "机房所在局站的ID，引用局站表SPC_STATION.STATION_ID字段。")
    @Length(max = 24, message = "最多24字符")
    @NotNull(message = "所属局站不能为空")
    private String stationId;

    /**
     * SPC_ROOM	ADDRESS	机房地址	机房地址意思是机房所在的地址，站址意思是机房所在局站的地址	VARCHAR2(255)	M
     */
    @Column(
            name = "ADDRESS",
            columnDefinition = "VARCHAR(255) COMMENT '机房地址,机房地址意思是机房所在的地址，站址意思是机房所在局站的地址。'",
            nullable = false
    )
    @ApiModelProperty(value = "机房地址", notes = "机房地址意思是机房所在的地址，站址意思是机房所在局站的地址。")
    @Length(max = 255, message = "最多255字符")
    @NotNull(message = "机房地址不能为空")
    private String address;

    /**
     * SPC_ROOM	STREET	所属街道、乡镇	机房所属街道、乡镇	VARCHAR2(255)	O
     */
    @Column(
            name = "STREET",
            columnDefinition = "VARCHAR(255) COMMENT '所属街道、乡镇\t机房所属街道、乡镇。'"
    )
    @ApiModelProperty(value = "所属街道", notes = "所属街道、乡镇\t机房所属街道、乡镇。")
    @Length(max = 255, message = "最多255字符")
    private String street;
    /**
     * SPC_ROOM	X	经度(GCJ02)	机房在地图上的经度坐标，gcj02火星坐标系。精确到小数点后六位。如：XXX．123456	NUMBER(20,10)	M
     */
    @Digits(integer=3, fraction=6,message = "机房在地图上的经度坐标，gcj02火星坐标系。精确到小数点后六位。如：XXX．123456")
    @Column(
            name = "X",
            columnDefinition = "NUMERIC(20,10) COMMENT '经度(GCJ02)\t机房在地图上的经度坐标，gcj02火星坐标系。精确到小数点后六位。如：XXX．123456\tNUMBER(20,10)'",
            nullable = false
    )
    @ApiModelProperty(value = "经度(GCJ02)",notes = "机房在地图上的经度坐标，gcj02火星坐标系。精确到小数点后六位。如：XXX．123456")
    @NotNull(message = "经度不能为空")
    private BigDecimal x;

    /**
     * SPC_ROOM	Y	纬度(GCJ02)	机房在地图上的纬度坐标，gcj02火星坐标系。精确到小数点后六位。如：XX．123456	NUMBER(20,10)	M
     */
    @Digits(integer=3, fraction=6,message = "机房在地图上的纬度坐标，gcj02火星坐标系。精确到小数点后六位。如：XX．123456")
    @Column(
            name = "Y",
            columnDefinition = "NUMERIC(20,10) COMMENT '纬度(GCJ02)\t机房在地图上的纬度坐标，gcj02火星坐标系。精确到小数点后六位。如：XX．123456'",
            nullable = false
    )
    @ApiModelProperty(value = "纬度(GCJ02)",notes = "机房在地图上的纬度坐标，gcj02火星坐标系。精确到小数点后六位。如：XX．123456")
    @NotNull(message = "纬度不能为空")
    private BigDecimal y;

    /**
     * SPC_ROOM	AREA	建筑面积	建筑面积,单位：平方米。	NUMBER(10,2)	O
     */
    @Digits(integer=8, fraction=2, message = "建筑面积,精度(8,2)")
    @Column(
            name = "AREA",
            columnDefinition = "NUMERIC(10,2) COMMENT '建筑面积\t建筑面积,单位：平方米。'"
    )
    @ApiModelProperty(value = "建筑面积",notes = "建筑面积,单位：平方米。")
    private  BigDecimal area;

    /**
     * SPC_ROOM	USED_AREA	已用面积	已用面积，单位：平方米。 	NUMBER(10,2)	O
     */
    @Digits(integer=8, fraction=2, message = "已用面积,精度(8,2)")
    @Column(
            name = "USED_AREA",
            columnDefinition = "NUMERIC(10,2) COMMENT '已用面积\t已用面积，单位：平方米。'"
    )
    @ApiModelProperty(value = "已用面积",notes = "已用面积，单位：平方米。")
    private  BigDecimal usedArea;

    /**
     * SPC_ROOM	TO_HIRE_RACK	可出租机架数	机房类型为IDC机房必填	NUMBER(10)	MC
     */
    @Column(
            name = "TO_HIRE_RACK",
            columnDefinition = "int(10) COMMENT '可出租机架数\t机房类型为IDC机房必填'"
    )
    @ApiModelProperty(value = "可出租机架数",notes = "机房类型为IDC机房必填")
    private int toHireRack;

    /**
     * SPC_ROOM	HIRED_RACK	已出租机架数	机房类型为IDC机房必填	NUMBER(10)	MC.
     *
     */
    @Column(
            name = "HIRED_RACK",
            columnDefinition = "int(10) COMMENT '已出租机架数\t机房类型为IDC机房必填'"
    )
    @ApiModelProperty(value = "已出租机架数",notes = "机房类型为IDC机房必填")
    private int hiredRack;

    /**
     * SPC_ROOM 	LENGTH	长度	长度，（单位m）	NUMBER(8，2)	O
     */
    @Digits(integer=8, fraction=2, message = "长度,精度(8,2)")
    @Column(
            name = "LENGTH",
            columnDefinition = "NUMERIC(8,2) COMMENT '长度\t长度，（单位m）'"
    )
    @ApiModelProperty(value = "长度",notes = "长度，（单位m）")
    private BigDecimal length;

    /**
     * SPC_ROOM	WIDTH	宽度	宽度，（单位m）	NUMBER(8，2)	O
     */
    @Digits(integer=8, fraction=2, message = "宽度,精度(8,2)")
    @Column(
            name = "WIDTH",
            columnDefinition = "NUMERIC(8,2) COMMENT '宽度\t宽度，（单位m）'"
    )
    @ApiModelProperty(value = "宽度",notes = "宽度，（单位m）")
    private BigDecimal width;

    /**
     * SPC_ROOM	HEIGHT	高度	高度，（单位m）	NUMBER(8，2)	O
     */
    @Digits(integer=8, fraction=2, message = "高度精度(8,2)")
    @Column(
            name = "HEIGHT",
            columnDefinition = "NUMERIC(8,2) COMMENT '高度\t高度，（单位m）'"
    )
    @ApiModelProperty(value = "高度",notes = "高度，（单位m）")
    private BigDecimal height;

    /**
     * SPC_ROOM	CLASS_ID	机房等级		NUMBER(8)	M.
     * <p>引用数据库字典值： 参见A.1　机房等级机房类型关系说明</p>
     */
    @Column(
            name = "CLASS_ID",
            columnDefinition = "INT(8) COMMENT '机房等级,引用数据库字典值： 参见A.1　机房等级机房类型关系说明'",
            nullable = false
    )
    @ApiModelProperty(value = "机房等级",allowableValues = "引用数据库字典值： 参见A.1　机房等级机房类型关系说明")
    @NotNull(message = "机房等级不能为空")
    @OptionVals(value = {"90218","90219","90230","90220","90221"}, message = "机房等级(classId)数据字典值:90218-A类机房;90219-B类机房;90230-B1类机房;90220-C1类机房;90221-C2类机房.")
    private Integer classId;

    /**
     * SPC_ROOM	TYPE_ID	机房类型	机房类型，通过机房等级分别取不同值，参见 A.1　机房等级机房类型关系说明	NUMBER(8)	M.
     */
    @Column(
            name = "TYPE_ID",
            columnDefinition = "INT(8) COMMENT '机房类型，通过机房等级分别取不同值，参见 A.1　机房等级机房类型关系说明'",
            nullable = false
    )
    @ApiModelProperty(value = "机房类型",allowableValues = "引用数据库字典值： 参见A.1　机房等级机房类型关系说明")
    @NotNull(message = "机房类型不能为空")
    @OptionVals(value = {"2050060","2050061","2050062","2050063","2050064","2050172","2050065","2050066","2050067",
            "2050068","2050069","2050070","2050053","2050071","2050072","2050073","2050074","2050075",
            "2050076","2050150","2050151","2050121"},
            message = "机房类型(typeId)数据字典值:2050060-长途传输机房;2050061-长途交换机房;2050062-长途IP机房;2050063-长途数据机房;" +
                    "2050064-长途专业综合机房;2050172-境外机房;2050065-本地核心交换机房;2050066-本地核心数据机房;" +
                    "2050067-本地核心专业综合机房;2050068-城域IP网核心机房;2050069-电力室;2050070-高级、低级信令转接点机房;" +
                    "2050053-IDC机房;2050071-本地城域网传输核心、汇聚、边缘层机房;2050072-本地城域网IP网汇聚层机房;" +
                    "2050073-本地交换端局机房;2050074-本地数据端局机房;2050075-本地专业综合机房;2050120-重要汇聚机房;" +
                    "2050076-中继机房;2050150-固网接入机房（有动环监控）;2050151-固网接入机房（无动环监控）;2050121-综合接入点")
    private Integer typeId;

    /**
     * SPC_ROOM	ROOM_TYPE_DETAIL	机房类型细类	NUMBER(8)	O
     * <p>
     * 若机房类型为接入网时，枚举值为：A级/B级/C级/D级；<br/>
     * 若机房类型为基站时，枚举值为：A级/B级/C级。<br/>
     * <ul>枚举值如下：
     * <li>2054300-A级</li>
     * <li>2054301-B级</li>
     * <li>2054302-C级</li>
     * <li>2054303-D级</li>
     * </ul>
     * </p>
     */
    @Column(
            name = "ROOM_TYPE_DETAIL",
            columnDefinition = "INT(8) COMMENT '若机房类型为接入网时，枚举值为：A级/B级/C级/D级;若机房类型为基站时，枚举值为：A级/B级/C级。枚举值如下：2054300-A级;2054301-B级;2054302-C级;2054303-D级.'"
    )
    @ApiModelProperty(value = "机房类型细类",allowableValues = "引用数据库字典值： 参见A.1　机房等级机房类型关系说明")
    private Integer roomTypeDetail;

    /**
     * SPC_ROOM	START_USE_DATE	投产时间	格式：YYYY-MM-DD hh:mm:ss	DATE(7)	M
     */
    @Column(
            name = "START_USE_DATE",
            columnDefinition = "DATETIME COMMENT '投产时间\t格式：YYYY-MM-DD hh:mm:ss.'",
            nullable = false
    )
    @ApiModelProperty(value = "机房类型细类", allowableValues = "格式：YYYY-MM-DD hh:mm:ss.")
    @NotNull(message = "投产时间不能为空")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date startUseDate;

    /**
     * SPC_ROOM	MAINTENANCE_UNIT	维护单位	填写具体的维护单位。	VARCHAR2(255)	O
     */
    @Column(
            name = "MAINTENANCE_UNIT",
            columnDefinition = "VARCHAR(255) COMMENT '维护单位\t填写具体的维护单位。'"
    )
    @ApiModelProperty(value = "维护单位", notes = "填写具体的维护单位。")
    @Length(max = 255, message = "维护单位最多255字符")
    private String maintenanceUnit;

    /**
     * SPC_ROOM	FLAG	是否基站机房	表征此机房是否为基站机房	NUMBER(8)	O
     * <ul>取值：
     * <li>是（1）</li>
     * <li>否（0）</li>
     * </ul>
     */
    @Column(
            name = "FLAG",
            columnDefinition = "INT(8) COMMENT '是否基站机房\t表征此机房是否为基站机房，取值：是（1）/否（0）'"
    )
    @ApiModelProperty(value = "是否基站机房", notes = "表征此机房是否为基站机房", allowableValues = "取值：是（1）/否（0）")
    private Integer flag;

    /**
     * SPC_ROOM	NOTES	备注	备注信息	VARCHAR2(255)	O
     */
    @Column(
            name = "NOTES",
            columnDefinition = "VARCHAR(255) COMMENT '备注\t备注信息'"
    )
    @ApiModelProperty(value = "备注", notes = "备注信息")
    @Length(max = 255, message = "备注最多255字符")
    private String Notes;


}
